package nix.anim.aop;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;

import eu.bitwalker.useragentutils.UserAgent;
import nix.anim.common.pojo.LogAnnotation;
import nix.anim.common.pojo.NixResult;
import nix.anim.pojo.LogOperation;
import nix.anim.pojo.User;
import nix.anim.sso.service.UserService;
import nix.anim.utils.CookieUtils;
import nix.anim.utils.HttpUtils;

/**
 * 操作日志记录Aspect
 */
public class LogAspect {

	@Autowired
	private UserService userService;
	
	@Value("${USER_SESSION_KEY}")
	private String USER_SESSION_KEY;
	
	@Autowired
	private JmsTemplate jsmTemplate;
	
	@Resource(name="logOperationQueueDestination")
	private Destination destination;

	private HttpServletRequest request;

	private HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	/**
	 * 前置通知：目标方法运行之前调用
	 */
	public void before() {
		// System.out.println("前置通知！");
	}

	/**
	 * 后置通知（如果方法出现异常不调用）：目标方法运行之后调用
	 */
	public void afterReturning() {
		// System.out.println("后置通知（如果方法出现异常不调用）！");
	}

	/**
	 * 环绕通知：在目标方法调用之前和之后调用，目标方法需要手动调用
	 */
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		// System.out.println("环绕通知之前！");
		// 手动执行方法
		Object proceed = pjp.proceed();
		// System.out.println("环绕通知之后！");
		try {
			this.request = getHttpServletRequest();
			// 获得方法名称
			String methodName = pjp.getSignature().getName();
			// 获得所有方法
			Method[] methods = pjp.getTarget().getClass().getMethods();
			for (Method method : methods) {
				LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
				if (logAnnotation != null && method.getName().equals(methodName)) {
					if (proceed instanceof NixResult) {
						NixResult result = (NixResult) proceed;
						if (result.getStatus() == 200) {
							// System.out.println(logAnnotation.action());
							// System.out.println(logAnnotation.operation());
							// System.out.println(Arrays.toString(pjp.getArgs()));
							// 获得User对象
							String token = CookieUtils.getCookieValue(request, USER_SESSION_KEY);
							NixResult resultUser = userService.getUserByToken(token);
							User user = (User) resultUser.getData();
							// 向ActiveMQ发送消息，记录登陆日志
							// 组装LogOperation对象
							final LogOperation logOperation = new LogOperation();
							logOperation.setUserId(user.getId());
							logOperation.setUsername(user.getUsername());
							logOperation.setOperated(new Date());
							logOperation.setAction(logAnnotation.action());
							logOperation.setObject(logAnnotation.object());
							logOperation.setOperation(Arrays.toString(pjp.getArgs()));
							logOperation.setIp(HttpUtils.getIpAddr(request));
							//logOperation.setLocation(HttpUtils.getAddresses(logOperation.getIp()));
							UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
							logOperation.setTerminal(userAgent.getBrowser() + " " + userAgent.getBrowserVersion());
							logOperation.setPlatform(userAgent.getOperatingSystem().getName());

							jsmTemplate.send(destination, new MessageCreator() {

								@Override
								public Message createMessage(Session session) throws JMSException {
									TextMessage textMessage = session.createTextMessage(JSON.toJSONString(logOperation));
									return textMessage;
								}
							});
						}
					} else {
						System.out.println("LogAspect: 不支持的返回值！");
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return proceed;
	}

	/**
	 * 异常通知：出现异常时调用
	 */
	public void afterException() {
		// System.out.println("异常通知");
	}

	/**
	 * 后置通知（出现异常也会调用）：
	 */
	public void after() {
		// System.out.println("后置通知（出现异常也会调用）");
	}
}
